package com.fm.jbsql.entry;

import com.fm.jbsql.util.*;

import java.util.logging.Logger;
import java.util.Vector;
import java.io.*;

import org.xml.sax.XMLReader;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.XMLReaderFactory;

/**
 * Created by IntelliJ IDEA.
 * User: syaroshenko
 * Date: Jul 13, 2006
 * Time: 11:36:27 AM
 * Class to manage svn entries file.
 */

/**
 * Class to manage svn entries file.
 */
final class ProjectSVN extends Project {
    private static final Logger logger = Logger.getLogger("com.fm.jbsql.entry.ProjectSVN");

    /**
     * Constructor.
     * @param _cmdopt command line arguments
     */
    public ProjectSVN(final CmdOpt _cmdopt) {
        super.setCmdOpt(_cmdopt);
    }

    /**
     * Parse entries.
     * @param f File
     * @param v Vector of resulting entries
     * @param bSrcShouldExist flag to throw error unless entries source exists
     * @param isGetRevisionMode mode to retrieve revision of pushed files only
     * @param inputFiles pushed files to retrieve revision
     * @throws NullPointerException
     * @throws JbsqlException
     */
    public void parseEntries(File f, Vector v, boolean bSrcShouldExist, boolean isGetRevisionMode, String []inputFiles) throws NullPointerException, JbsqlException {
        logger.fine("start");
        super.parseEntries(f, v, bSrcShouldExist, isGetRevisionMode, inputFiles);

        try {
            if ( isEntriesFormatSVN14(f, isGetRevisionMode) ) {
                SvnEntryPlainTextHandler handler = new SvnEntryPlainTextHandler(v, isGetRevisionMode, inputFiles);
                SvnEntryReader xr = new SvnEntryReader();
                xr.setContentHandler(handler);
                xr.parse(f);
            }
            else {
                SvnEntryXMLHandler handler = new SvnEntryXMLHandler(v, isGetRevisionMode, inputFiles);
                XMLReader xr;
                try { xr = XMLReaderFactory.createXMLReader(); }
                catch (SAXException ex1) {
                    try { xr = XMLReaderFactory.createXMLReader("org.apache.crimson.parser.XMLReaderImpl"); }
                    catch(SAXException ex2) { throw new JbsqlException("SAX_01", f.getName(), ex2); }
                }
                xr.setContentHandler(handler);
                xr.setErrorHandler(handler);

                FileReader r = new FileReader(f);
                xr.parse(new InputSource(r));
            }
        }
        catch (FileNotFoundException ex) {
            if ( bSrcShouldExist ) {
                throw new JbsqlException("FNF_01", f.getName(), ex);
            }
            else logger.info("No entries source found, skipping.");
        }
        catch (IOException ex) {
            throw new JbsqlException("IOE_04", f.getName(), ex);
        }
        catch (SAXException ex) {
            throw new JbsqlException("SAX_01", f.getName(), ex);
        }
        logger.fine("finish");
    }

    /**
     * Verify if listed files physically exist.
     */
    void verifyEntrySourceIntegrity() {}

    /**
     * Get format of entries file: can be XML (old), or non-XML (new)
     * @param f
     * @param bSrcShouldExist
     * @return true for new non-XML format, false otherwise
     * @throws JbsqlException
     */
    static boolean isEntriesFormatSVN14(File f, boolean bSrcShouldExist) throws JbsqlException {
        String s;
        BufferedReader is = null;
        try {
            is = new BufferedReader(new InputStreamReader(new FileInputStream(f), "UTF8"));
            // check first line, it should contain value of >= 4
            return !((s = is.readLine()) == null || s.trim().length() == 0 || !Character.isDigit(s.charAt(0)) || (int)s.charAt(0) - (int)'0' < 4);
        }
        catch (FileNotFoundException ex) {
            if ( bSrcShouldExist ) {
                throw new JbsqlException("FNF_01", f.getName(), ex);
            }
            else logger.info("No entries source found, skipping.");
        }
        catch (IOException ex) {
            throw new JbsqlException("IOE_04", f.getName(), ex);
        }
        finally {
            if ( is != null ) try {is.close();} catch(IOException ex){ex.printStackTrace();}
        }
        return false;
    }
}

